---
title: Send one keyword update to OnBase
summary: Builds the OnBase E-Form payload and sends one keyword update over SOAP, synchronously or asynchronously.
status: draft
owner: Documents
last_reviewed: 2026-09-17
operation_id: OP-005
trigger: Step 4 of OP-003
---

# OP-005: Send one keyword update to OnBase

For each `KeywordUpdate` that OP-004 decided to send, this operation builds the OnBase E-Form payload with one keyword action, invokes the SOAP client either synchronously or asynchronously, throttles with a configured sleep, and logs the result.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-005 |
| **Trigger** | Step 4 of [OP-003](sync-a-keyword-batch-with-onbase.md) |
| **Lifecycle stage** | Execute |
| **Owning component** | `OnBaseKeywordSyncClient.UpdateKeyword(KeywordUpdate update, ImageKeywordSync keyword)`, invoked from `KeywordUpdater.UpdateKeyword` |
| **Inputs** | One `KeywordUpdate`, the owning `ImageKeywordSync` record |
| **Outputs** | One SOAP call to OnBase; a document handle when synchronous |
| **Failure exit code** | `5` — an unmapped `DocTypeGroup` or a WCF fault/timeout propagates |

## Steps

1. Log the update's type and key, and (when counting) the document count ([BR-OBKS-006](../business-rules.md#br-obks-006-trigger-type-and-query-keyword-derived-by-precedence))
2. Build `OBEFormDataKeywordUpdate`: `Single_Instance_Keyword_Group.QueryType.INS_CustomQuery` = the custom query mapped from the record's `DocTypeGroup` via `OnBaseKeywordSync.customquerymappings`; `StandAlone.INS_RequestType_Collection` = `ASYNCHRONOUS`/`SYNCHRONOUS`; `StandAlone.INS_Username_Collection` = `Environment.UserName` ([BR-OBKS-008](../business-rules.md#br-obks-008-custom-query-selected-from-doc-type-group-mapping))
   - On failure: an unmapped `DocTypeGroup` throws `KeyNotFoundException` → exit code `5`
3. Add one `QueryParameter`: `INS_QueryKeywordType` = `CLAIM NUMBER` / `POLICY NUMBER` / `AGENCY NUMBER` / `GROUP ACRONYM` from the `KeywordUpdate`; operator `EQUAL`; relation `AND`; value = the update's key ([BR-OBKS-006](../business-rules.md#br-obks-006-trigger-type-and-query-keyword-derived-by-precedence))
4. Add one `KeywordUpdateAction` at order `0`: `INS_Action` = `DELETE` when the new value is null/whitespace else `ADD`; `INS_DataType` = `OnBaseKeyword`; `INS_DataValue` = upper-cased new value (null on delete) ([BR-OBKS-007](../business-rules.md#br-obks-007-empty-new-value-applied-as-keyword-deletion), [BR-OBKS-009](../business-rules.md#br-obks-009-flag-keyword-translation))
5. Call `KeywordUpdateAsync(data)` when async (`Task` not awaited), else `KeywordUpdate(data)` and capture the returned document handle ([BR-OBKS-001](../business-rules.md#br-obks-001-asynchronous-or-synchronous-update-mode))
   - On failure: a WCF fault/timeout throws → exit code `5`
6. Sleep `OnBaseKeywordSync.onbaseclientsleepmilliseconds` when greater than zero ([BR-OBKS-011](../business-rules.md#br-obks-011-onbase-calls-throttled-by-a-sleep-interval))
7. Log `"Update sent to OnBase"` (async) or `"Update sent to OnBase - update doc handle: {docHandle}"` (sync) ([BR-OBKS-001](../business-rules.md#br-obks-001-asynchronous-or-synchronous-update-mode))

Payload finding: `Multi_Instance_Keyword_Group.KeywordUpdateAction_Collection` is allocated with exactly one element and `AddKeywordUpdateAction` is called once with `actionOrder = 0`, so each SOAP call carries exactly one keyword action.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
    A["Log update type and key"] --> B["Build OBEFormDataKeywordUpdate<br>map DocTypeGroup to custom query"]
    B --> C["Add QueryParameter<br>from update key"]
    C --> D["Add one KeywordUpdateAction<br>ADD or DELETE"]
    D --> E{"Async mode?"}
    E -->|Yes| F["KeywordUpdateAsync -<br>fire and forget"]
    E -->|No| G["KeywordUpdate -<br>capture doc handle"]
    F --> H["Sleep sleepmilliseconds<br>if greater than zero"]
    G --> H
    H --> I["Log update sent to OnBase"]
    B -.->|Unmapped DocTypeGroup| ERR["Exit code 5"]
    F -.->|WCF fault/timeout| ERR
    G -.->|WCF fault/timeout| ERR
```

## Logging

| Log id | Written content |
| --- | --- |
| Not application-assigned (fans out to all registered `file0`–`file4` writers) | Update type/key, optional document count, `"Update sent to OnBase"` (async) or `"Update sent to OnBase - update doc handle: {n}"` (sync) |

## Error handling
- An unmapped `DocTypeGroup` raises `KeyNotFoundException`; a malformed mapping string raises `IndexOutOfRangeException`. Both propagate to `OnBaseKeywordSyncRunner.Execute`'s catch block → exit code `5`.
- A WCF fault or timeout on either `KeywordUpdate` or `KeywordUpdateAsync` propagates the same way. The async path's `Task` is never awaited or observed, so faults on that path are silently lost rather than reaching this catch block*.

## Related documentation
- [Run lifecycle](../run-lifecycle.md)
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)
- [Operational runbook](../operational-runbook.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

## Sources
- `OnBaseKeywordSync/Services/OnBaseKeywordSyncClient.cs`
- `OnBaseKeywordSync/Services/KeywordUpdater.cs`
- `OnBaseKeywordSync/Contracts/KeywordUpdateExtensions.cs`
- `OnBaseKeywordSync/Service References/OnBase/Reference.cs`
